.\" Copyright (c) 2019-2024 Oracle.  All rights reserved.
.\"
.\" %%%LICENSE_START(GPLv2+_DOC_FULL)
.\" SPDX-License-Identifier: GPL-2.0-or-later
.\" %%%LICENSE_END
.TH IOCTL-XFS-GETPARENTS 2 2024-04-09 "XFS"
.SH NAME
ioctl_xfs_getparents \- query XFS directory parent information
.SH SYNOPSIS
.br
.B #include <xfs/xfs_fs.h>
.PP
.BI "int ioctl(int " fd ", XFS_IOC_GETPARENTS, struct xfs_getparents *" arg );
.PP
.BI "int ioctl(int " fd ", XFS_IOC_GETPARENTS_BY_HANDLE, struct xfs_getparents_by_handle *" arg );
.SH DESCRIPTION
This command is used to retrieve the directory parent pointers of either the
currently opened file or a file handle.
Parent pointers point upwards in the directory tree from a child file towards a
parent directories.
Each entry in a parent directory must have a corresponding parent pointer in
the child.

Calling programs should allocate a large memory buffer and initialize a header
of the following form:
.PP
.in +4n
.nf
struct xfs_getparents {
	struct xfs_attrlist_cursor  gp_cursor;
	__u16                       gp_iflags;
	__u16                       gp_oflags;
	__u32                       gp_bufsize;
	__u64                       __pad;
	__u64                       gp_buffer;
};

struct xfs_getparents {
	struct xfs_handle           gph_handle;
	struct xfs_getparents       gph_request;
};
.fi
.in

.PP
The field
.I gp_cursor
tracks the progress of iterating through the parent pointers.
Calling programs must initialize this to zero before the first system call
and must not touch it after that.

.PP
The field
.I gp_iflags
control the behavior of the query operation and provide more information
about the outcome of the operation.
There are no input flags currently defined; this field must be zero.

.PP
The field
.I gp_oflags
contains information about the query itself.
Possibly output flags are:
.RS 0.4i
.TP
.B XFS_GETPARENTS_OFLAG_ROOT
The file queried was the root directory.
.TP
.B XFS_GETPARENTS_OFLAG_DONE
There are no more parent pointers to query.
.RE

.PP
The field
.I __pad
must be zero.

.PP
The field
.I gp_bufsize
should be set to the size of the buffer, in bytes.

.PP
The field
.I gp_buffer
should point to an output buffer for the parent pointer records.

Parent pointer records are returned in the following form:
.PP
.in +4n
.nf

struct xfs_getparents_rec {
	struct xfs_handle           gpr_parent;
	__u16                       gpr_reclen;
	char                        gpr_name[];
};
.fi
.in

.PP
The field
.I gpr_parent
is a file handle that can be used to open the parent directory.

.PP
The field
.I gpr_reclen
will be set to the number of bytes used by this parent record.

.PP
The array
.I gpr_name
will be set to a NULL-terminated byte sequence representing the filename
stored in the parent pointer.
If the name is a zero-length string, the file queried has no parents.

.SH SAMPLE PROGRAM
Calling programs should allocate a large memory buffer, initialize the head
structure to zeroes, set gp_bufsize to the size of the buffer, and call the
ioctl.
The XFS_GETPARENTS_OFLAG_DONE flag will be set in gp_flags when there are no
more parent pointers to be read.
The below code is an example of XFS_IOC_GETPARENTS usage:

.nf
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <xfs/linux.h>
#include <xfs/xfs.h>
#include <xfs/xfs_types.h>
#include <xfs/xfs_fs.h>

int main() {
	struct xfs_getparents gp = { };
	struct xfs_getparents_rec *gpr;
	int error, fd;

	gp.gp_buffer = (uintptr_t)malloc(65536);
	if (!gp.gp_buffer) {
		perror("malloc");
		return 1;
	}
	gp->gp_bufsize = 65536;

	fd = open("/mnt/test/foo.txt", O_RDONLY | O_CREAT);
	if (fd  == -1)
		return errno;

	do {
		error = ioctl(fd, XFS_IOC_GETPARENTS, gp);
		if (error)
			return error;

		for (gpr = xfs_getparents_first_rec(&gp);
		     gpr != NULL;
		     gpr = xfs_getparents_next_rec(&gp, gpr)) {
			if (gpr->gpr_name[0] == 0)
				break;

			printf("inode		= %llu\\n",
					gpr->gpr_parent.ha_fid.fid_ino);
			printf("generation	= %u\\n",
					gpr->gpr_parent.ha_fid.fid_gen);
			printf("name		= \\"%s\\"\\n\\n",
					gpr->gpr_name);
		}
	} while (!(gp.gp_flags & XFS_GETPARENTS_OFLAG_DONE));

	return 0;
}
.fi

.SH RETURN VALUE
On error, \-1 is returned, and
.I errno
is set to indicate the error.
.PP
.SH ERRORS
Error codes can be one of, but are not limited to, the following:
.TP
.B EFSBADCRC
Metadata checksum validation failed while performing the query.
.TP
.B EFSCORRUPTED
Metadata corruption was encountered while performing the query.
.TP
.B EINVAL
One or more of the arguments specified is invalid.
.TP
.B EMSGSIZE
The record buffer was not large enough to store even a single record.
.TP
.B ENOMEM
Not enough memory to retrieve parent pointers.
.TP
.B EOPNOTSUPP
Repairs of the requested metadata object are not supported.
.TP
.B EROFS
Filesystem is read-only and a repair was requested.
.TP
.B ESHUTDOWN
Filesystem is shut down due to previous errors.
.TP
.B EIO
An I/O error was encountered while performing the query.
.SH CONFORMING TO
This API is specific to XFS filesystem on the Linux kernel.
.SH SEE ALSO
.BR ioctl (2)
